package com.qianyu.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qianyu.config.Constants;
import com.qianyu.entity.bean.QqAccount;
import com.qianyu.entity.bean.Qun;
import com.qianyu.entity.bean.QunMember;
import com.qianyu.entity.bean.QunYj;
import com.qianyu.entity.vo.QqMemberVo;
import com.qianyu.entity.vo.QunMemberKeepQhVo;
import com.qianyu.mapper.QunMemberMapper;
import com.qianyu.service.QqAccountService;
import com.qianyu.service.QunMemberService;
import com.qianyu.service.QunService;
import com.qianyu.service.QunYjService;
import com.qianyu.util.CacheKeyUtil;
import com.qianyu.util.RedisUtil;
import com.qianyu.util.TimeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class QunMemberBhTask {

    private final RedisUtil redisUtil;

    private final QunService qunService;

    private final QunMemberService qunMemberService;

    private final QqAccountService qqAccountService;


    private final QunYjService qunYjService;

    private final QunMemberMapper qunMemberMapper;


    /**
     * 每30s自动补号到群成员
     */
    @Async
    @Scheduled(cron = "0/30 * * * * ?")
    public void authAddMember() {
        List<QunMember> autoMembers = new ArrayList<>();
        //获取创建成功的群
        List<Qun> quns = qunService.list(Wrappers.<Qun>lambdaQuery().eq(Qun::getStatus, 1));
        List<Long> qunIds = quns.stream().map(Qun::getId).collect(Collectors.toList());
        List<QunMember> qunMembers = qunMemberService.list(Wrappers.<QunMember>lambdaQuery().eq(QunMember::getStatus, 0).or(q -> q.eq(QunMember::getStatus, 1)));
        List<QunYj> qunYjs = qunYjService.list(Wrappers.<QunYj>lambdaQuery().in(CollectionUtil.isNotEmpty(qunIds),
                        QunYj::getQunId, quns.stream().map(Qun::getId).collect(Collectors.toList()))
                .and(q -> q.last(" LENGTH(qq) = 0")));
        Map<Long, List<QunMember>> listMap = qunMembers.stream().collect(Collectors.groupingBy(QunMember::getQunId));
        for (Qun qun : quns) {
            List<QunMember> members = listMap.get(qun.getId());
            List<QunMember> fblist = members.stream().filter(m -> m.getRole().equals(1)).collect(Collectors.toList());
            List<QunMember> lblist = members.stream().filter(m -> m.getRole().equals(2)).collect(Collectors.toList());
            //该群应有的发包数量
            Integer fbNum = qun.getYjNum();
            //该群应有的领包数量
            Integer lbNum = qun.getConfClaimQnum();

            if (fbNum > fblist.size()) {
                //补发包账号
                List<QqAccount> accounts = qqAccountService.getAccounts(1, fbNum - fblist.size());
                //筛选群云机
                List<QunYj> yjs = qunYjs.stream().filter(q -> q.getRole().equals(1)).filter(q -> q.getQunId().equals(qun.getId())).collect(Collectors.toList());
                for (int i = 0; i < accounts.size() && i < yjs.size(); i++) {
                    QqAccount account = accounts.get(i);
                    QunYj yj = yjs.get(i);
                    QunMember member = new QunMember() {{
                        setQq(account.getQq());
                        setRole(1);
                        setQunId(qun.getId());
                        setJoinTime(DateTime.now());
                        setStatus(0);
                    }};
                    yj.setQq(account.getQq());
                    autoMembers.add(member);
                    qunYjService.updateById(yj);
                }

            }
            if (lbNum > lblist.size()) {
                //补领包账号
                List<QqAccount> lhAccounts = qqAccountService.getAccounts(2, lbNum - lblist.size());
                //筛选群云机
                List<QunYj> yjs = qunYjs.stream().filter(q -> q.getRole().equals(2)).filter(q -> q.getQunId().equals(qun.getId())).collect(Collectors.toList());
                for (int i = 0; i < lhAccounts.size() && i < yjs.size(); i++) {
                    QqAccount account = lhAccounts.get(i);
                    QunYj yj = yjs.get(i);
                    QunMember member = new QunMember() {{
                        setQq(account.getQq());
                        setRole(1);
                        setQunId(qun.getId());
                        setJoinTime(new Date());
                        setStatus(0);
                    }};
                    yj.setQq(account.getQq());
                    autoMembers.add(member);
                    qunYjService.updateById(yj);
                }
            }
            //添加群成员
            if (CollectionUtil.isNotEmpty(autoMembers)) {
                qunMemberService.saveBatch(autoMembers);
            }

        }
    }

    /**
     * 每天凌晨0点0分0秒执行
     */
    @Async
    @Scheduled(cron = "0 0 0 * * ?")
    public void addMembersToCache() {
        if (redisUtil.hasKey(CacheKeyUtil.addMembersToCacheSet())) {
            redisUtil.del(CacheKeyUtil.addMembersToCacheSet());
        }
        List<QqMemberVo> memberVos = qunMemberMapper.joinQun(TimeUtil.toExpireDate(Constants.keepTimeHour, Calendar.MINUTE));
        for (QqMemberVo v : memberVos) {
            redisUtil.lSet(CacheKeyUtil.addMembersToCacheSet(), v);
        }
        if (redisUtil.hasKey(CacheKeyUtil.addMembersToCacheSet())) {
            redisUtil.expire(CacheKeyUtil.addMembersToCacheSet(), Constants.memberCacheSet);
        }
    }


    /**
     * 每天凌晨0点0分0秒执行
     */
    @Async
    @Scheduled(cron = "0 0 0 * * ?")
    public void keepQhToCache() {
        if (redisUtil.hasKey(CacheKeyUtil.keepQhSet())) {
            redisUtil.del(CacheKeyUtil.keepQhSet());
        }
        List<QunMemberKeepQhVo> keepQhVos = qunMemberMapper.keepQh(TimeUtil.toExpireDate(Constants.keepTimeHour, Calendar.HOUR_OF_DAY),
                TimeUtil.toExpireDate(Constants.keepGetTimeHour, Calendar.HOUR_OF_DAY));
        for (QunMemberKeepQhVo vo : keepQhVos) {
            redisUtil.lSet(CacheKeyUtil.keepQhSet(), vo);
        }
        if (redisUtil.hasKey(CacheKeyUtil.keepQhSet())) {
            redisUtil.expire(CacheKeyUtil.keepQhSet(), Constants.keepQhToCache);
        }
    }
}
